﻿using System;
using System.Collections.Generic;
using System.Text;
using Sinacor.Infra.Service.Common;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;
using Sinacor.Infra.Service.Validation;
using Sinacor.Servico.Bovespa.Acesso;

namespace Sinacor.Servico.Bovespa.Movimento.BusinessLogic
{
    public class ControleMovimentoOrdens : BaseBusinessLogic
    {
        #region Métodos Públicos

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public BusinessEntity.DataMovimento AbrirMovimento()
        {
            Acesso.BusinessEntity.Parameter.VerificarAcessoFuncao verificarAcesso = new Acesso.BusinessEntity.Parameter.VerificarAcessoFuncao();
            verificarAcesso.Funcao = "ABER";

            if (new Acesso.BusinessLogic.Acesso().VerificarAcessoFuncao(verificarAcesso))            
            {
                BusinessEntity.Resultado resultado = this.ValidarControleMovimento(BusinessEntity.Enum.TipoMovimento.Aberto);

                if (resultado.Sucesso)
                {
                    resultado = new ResourceAccess.ControleMovimentoOrdens().AbrirMovimento();

                    if (resultado.Sucesso)
                    {
                        this.AlterarEstadoMovimento(BusinessEntity.Enum.TipoMovimento.Aberto);

                        BusinessEntity.DataMovimento dataMovimento = new BusinessEntity.DataMovimento();
                        dataMovimento.Valor = resultado.DataMovimento;

                        return dataMovimento;
                    }
                    else
                    {
                        if (resultado.CodigoErro == -1)
                            throw new BusinessException(109209);
                        else
                            this.TratarExcecoes(resultado);
                    }
                }
                else
                {
                    if(resultado.CodigoErro == -1)
                        throw new BusinessException(109208);
                    else
                        this.TratarExcecoes(resultado);
                }
            }
            else
                throw new BusinessException(109077);

            return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public BusinessEntity.DataMovimento CalcularDataAberturaMovimento()
        {
            BusinessEntity.Parameter.SistemaBovespa sistemaBovespa = new BusinessEntity.Parameter.SistemaBovespa();
            sistemaBovespa.Sistema = Sinacor.Servico.Bovespa.Movimento.BusinessEntity.Enum.TipoSistema.Ordens;

            BusinessEntity.Resultado resultado = new ResourceAccess.ControleMovimento().CalcularDataAberturaMovimento(sistemaBovespa);

            if (resultado.Sucesso)
            {
                BusinessEntity.DataMovimento dataMovimento = new BusinessEntity.DataMovimento();
                dataMovimento.Valor = resultado.DataMovimento;
                return dataMovimento;
            }
            else
                this.TratarExcecoes(resultado);

            return null;
        }

        /// <summary>
        /// 
        /// </summary>
        public void ConsolidarMovimento()
        {
            Acesso.BusinessEntity.Parameter.VerificarAcessoFuncao verificarAcesso = new Acesso.BusinessEntity.Parameter.VerificarAcessoFuncao();
            verificarAcesso.Funcao = "FECH";

            if (new Acesso.BusinessLogic.Acesso().VerificarAcessoFuncao(verificarAcesso))
            {
                if (this.ObterEstadoMovimento().Estado == BusinessEntity.Enum.TipoMovimento.Aberto)
                {
                    BusinessEntity.Resultado resultado = new ResourceAccess.ControleMovimentoOrdens().ExecutarFuncaoFechamento(BusinessEntity.Enum.TipoFechamento.Consolidacao);
                    if (!resultado.Sucesso)
                    {
                        if (resultado.CodigoErro == -1)
                            throw new BusinessException(109214);
                        else
                            this.TratarExcecoes(resultado);
                    }
                }
                else
                    throw new BusinessException(109245);
            }
            else
                throw new BusinessException(109102);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        public void FecharMovimento(BusinessEntity.Parameter.DadosFechaMovimento request)
        {
            if (request == null)
                throw new BusinessException(109144);

            Acesso.BusinessEntity.Parameter.VerificarAcessoFuncao verificarAcesso = new Acesso.BusinessEntity.Parameter.VerificarAcessoFuncao();
            verificarAcesso.Funcao = "FECH";

            if (new Acesso.BusinessLogic.Acesso().VerificarAcessoFuncao(verificarAcesso))
            {
                BusinessEntity.Resultado resultado = this.ValidarControleMovimento(BusinessEntity.Enum.TipoMovimento.Fechado);

                if (!resultado.Sucesso)
                {
                    if(resultado.CodigoErro == -1)
                        throw new BusinessException(109210);
                    else
                        this.TratarExcecoes(resultado);
                }

                BusinessEntity.DataMovimento dataMovimento = new BusinessEntity.DataMovimento();
                dataMovimento.Valor = request.DataMovimento;

                resultado = this.VerificarInconsistenciasFechamento(dataMovimento);

                if (!resultado.Sucesso)
                {
                    if (request.ContinuaHavendoInconsistencias)
                    {
                        resultado = this.GravarInconsistencias();

                        if (resultado.Sucesso)
                        {
                            resultado = new ResourceAccess.ControleMovimentoOrdens().ValidarFechamentoMovimento(dataMovimento);

                            if (resultado.Sucesso)
                            {
                                this.AlterarEstadoMovimento(BusinessEntity.Enum.TipoMovimento.ProcessoFechamento);
                                resultado = new ResourceAccess.ControleMovimentoOrdens().ExecutarFuncaoFechamento(BusinessEntity.Enum.TipoFechamento.Fechamento);

                                if (resultado.Sucesso)
                                    this.AlterarEstadoMovimento(BusinessEntity.Enum.TipoMovimento.Fechado);
                                else
                                {
                                    if(resultado.CodigoErro == -1)
                                        throw new BusinessException(109213);
                                    else
                                        this.TratarExcecoes(resultado);
                                }
                            }
                            else
                            {
                                if(resultado.CodigoErro == -1)
                                    throw new BusinessException(109212);
                                else
                                    throw new BusinessException(109182);
                            }
                        }
                        else
                        {
                            if(resultado.CodigoErro == -1)
                                throw new BusinessException(109211);                                
                            else
                                this.TratarExcecoes(resultado);
                        }
                    }
                    else
                        throw new BusinessException(109111);
                }
                else
                {
                    resultado = new ResourceAccess.ControleMovimentoOrdens().ValidarFechamentoMovimento(dataMovimento);

                    if (resultado.Sucesso)
                    {
                        this.AlterarEstadoMovimento(BusinessEntity.Enum.TipoMovimento.ProcessoFechamento);
                        resultado = new ResourceAccess.ControleMovimentoOrdens().ExecutarFuncaoFechamento(BusinessEntity.Enum.TipoFechamento.Fechamento);

                        if (resultado.Sucesso)
                            this.AlterarEstadoMovimento(BusinessEntity.Enum.TipoMovimento.Fechado);
                        else
                        {
                            if(resultado.CodigoErro == -1)
                                throw new BusinessException(109213);
                            else
                                this.TratarExcecoes(resultado);
                        }
                    }
                    else
                    {
                        if(resultado.CodigoErro == -1)
                            throw new BusinessException(109212);
                        else
                            throw new BusinessException(109182);
                    }
                }
            }
            else
                throw new BusinessException(109079);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public BusinessEntity.EstadoMovimento ObterEstadoMovimento()
        {
            return new ResourceAccess.ControleMovimentoOrdens().ObterEstadoMovimento();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public BusinessEntity.InformacoesMovimento ObterInformacoesMovimento(BusinessEntity.DataMovimento request)
        {
            return new ResourceAccess.ControleMovimentoOrdens().ObterInformacoesMovimento(request);
        }

        /// <summary>
        /// 
        /// </summary>
        public void ReabrirMovimento()
        {
            Acesso.BusinessEntity.Parameter.VerificarAcessoFuncao verificarAcesso = new Acesso.BusinessEntity.Parameter.VerificarAcessoFuncao();
            verificarAcesso.Funcao = "ABER";

            if (new Acesso.BusinessLogic.Acesso().VerificarAcessoFuncao(verificarAcesso))
            {
                BusinessEntity.Resultado resultado = this.ValidarControleMovimento(Sinacor.Servico.Bovespa.Movimento.BusinessEntity.Enum.TipoMovimento.Reaberto);
                if (resultado.Sucesso)
                    this.AlterarEstadoMovimento(BusinessEntity.Enum.TipoMovimento.Aberto);
                else
                {
                    if(resultado.CodigoErro == -1)
                        throw new BusinessException(109216);
                    else
                        this.TratarExcecoes(resultado);
                }
            }
            else
                throw new BusinessException(109078);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public BusinessEntity.Resultado SimularFechamentoMovimento(BusinessEntity.DataMovimento request)
        {
            if(request == null)
                throw new BusinessException(109183);

            BusinessEntity.Resultado resultado = new BusinessEntity.Resultado();

            if (this.ObterEstadoMovimento().Estado == BusinessEntity.Enum.TipoMovimento.Aberto)
            {
                resultado = this.VerificarInconsistenciasFechamento(request);

                if (resultado.Sucesso)
                {
                    resultado = this.ValidarFechamentoMovimento(request);
                    if (!resultado.Sucesso)
                        resultado.ImpedeFechamento = true;
                }
                else
                    resultado.ImpedeFechamento = false;
            }
            else
                throw new BusinessException(109246);

            return resultado;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public BusinessEntity.Resultado VerificarAlertasFechamento(BusinessEntity.DataMovimento request)
        {
            if (request == null)
                throw new BusinessException(109184);

            BusinessEntity.Resultado resultado = this.ValidarControleMovimento(BusinessEntity.Enum.TipoMovimento.Fechado);
            if (resultado.Sucesso)
                resultado = this.VerificarInconsistenciasFechamento(request);
            else
            {
                if(resultado.CodigoErro == -1)
                    throw new BusinessException(109215);
                else
                    this.TratarExcecoes(resultado);
            }

            return resultado;
        }

        public void RemontarCalendario()
        {
            BusinessEntity.Parameter.FiltroRemontaCalendario filtro = new BusinessEntity.Parameter.FiltroRemontaCalendario { Sistema = BusinessEntity.Enum.TipoSistema.Ordens };
            ResourceAccess.ControleMovimento raControleMovimento = new ResourceAccess.ControleMovimento();
            BusinessEntity.Resultado resultado = raControleMovimento.RemontarCalendario(filtro);

            if (!resultado.Sucesso)
                this.TratarExcecoes(resultado);
        }

        #endregion

        #region Métodos Privados

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private BusinessEntity.Resultado ValidarControleMovimento(BusinessEntity.Enum.TipoMovimento request)
        {
            return new ResourceAccess.ControleMovimentoOrdens().ValidarControleMovimento(request);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        private void TratarExcecoes(BusinessEntity.Resultado request)
        {
            List<Object> _params;

            if (string.IsNullOrEmpty(request.Argumentos))
            {
                throw new BusinessException(request.CodigoErro);
            }
            else
            {
                _params = ErrorMessage.ConvertXmlArgumentsToParameters(request.Argumentos);

                if (_params != null)
                    throw new BusinessException(request.CodigoErro, _params.ToArray());
                else
                    throw new BusinessException(request.CodigoErro);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        private void AlterarEstadoMovimento(BusinessEntity.Enum.TipoMovimento request)
        {
            new ResourceAccess.ControleMovimentoOrdens().AlterarEstadoMovimento(request);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private BusinessEntity.Resultado VerificarInconsistenciasFechamento(BusinessEntity.DataMovimento request)
        {
            if(request == null)
                throw new BusinessException(109145);

            return new ResourceAccess.ControleMovimentoOrdens().VerificarInconsistenciasFechamento(request);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private BusinessEntity.Resultado GravarInconsistencias()
        {
            return new ResourceAccess.ControleMovimentoOrdens().GravarInconsistencias();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private BusinessEntity.Resultado ValidarFechamentoMovimento(BusinessEntity.DataMovimento request)
        {
            return new ResourceAccess.ControleMovimentoOrdens().ValidarFechamentoMovimento(request);
        }

        #endregion
    }
}
